package com.zijidelu.luframework.api.model;

import com.zijidelu.luframework.base.exception.BizException;
import com.zijidelu.luframework.base.message.Message;
import com.zijidelu.luframework.base.message.impl.GenericMessage;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;

/**
 * 返回值类。
 *
 * @author ZIJIDELU
 * @date 2024/1/8 23:39
 */
public class ApiResult<T> implements Serializable {
    @Serial
    private static final long serialVersionUID = 44241729340886204L;

    private Integer code;
    private String message;
    private Boolean success;
    private T payload;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Boolean isSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public T getPayload() {
        return payload;
    }

    public void setPayload(T payload) {
        this.payload = payload;
    }

    /**
     * 成功结果。
     *
     * @param code 状态码
     * @param data 数据
     * @param <T>  数据类型
     * @return 成功结果
     */
    public static <T> ApiResult<T> successOf(final Integer code, final String message, final T data) {

        ApiResult<T> apiResult = new ApiResult<>();
        apiResult.setCode(code);
        apiResult.setMessage(message);
        apiResult.setSuccess(true);
        apiResult.setPayload(data);

        return apiResult;
    }

    /**
     * 成功结果。
     *
     * @param data 数据
     * @param <T>  数据类型
     * @return 成功结果
     */
    public static <T> ApiResult<T> successOf(final T data) {
        return ApiResult.toResult(GenericMessage.SUCCESS, data);
    }

    /**
     * 成功结果。
     *
     * @param msg 成功信息
     * @param <T> 数据类型
     * @return 成功结果
     */
    public static <T> ApiResult<T> successOf(final String msg) {
        return successOf(GenericMessage.SUCCESS.getCode(), msg, null);
    }

    /**
     * 失败结果。
     *
     * @param code    状态码
     * @param message 错误信息
     * @param data    数据
     * @param <T>     数据类型
     * @return 失败结果
     */
    public static <T> ApiResult<T> failOf(final Integer code, final String message, final T data) {
        ApiResult<T> apiResult = new ApiResult<>();
        apiResult.setCode(code);
        apiResult.setMessage(message);
        apiResult.setSuccess(false);
        apiResult.setPayload(data);

        return apiResult;
    }

    /**
     * 失败结果。
     *
     * @param data 数据
     * @param <T>  数据类型
     * @return 失败结果
     */
    public static <T> ApiResult<T> failOf(final T data) {
        return ApiResult.toResult(GenericMessage.BIZ_EXCEPTION, data);
    }

    /**
     * 失败结果。
     *
     * @param msg 错误信息
     * @param <T> 数据类型
     * @return 失败结果
     */
    public static <T> ApiResult<T> failOf(final String msg) {
        return failOf(GenericMessage.BIZ_EXCEPTION.getCode(), msg, null);
    }

    /**
     * 转换结果类型。
     *
     * @param apiResult result
     * @param <T>       结果data类型
     * @return 新的result
     */
    public static <T> ApiResult<T> cast(final ApiResult<?> apiResult) {
        return cast(apiResult, null);
    }

    /**
     * 转换结果类型。
     *
     * @param apiResult result
     * @param <T>       结果data类型
     * @return 新的result
     */
    public static <T> ApiResult<T> cast(final ApiResult<?> apiResult, final T data) {
        Objects.requireNonNull(apiResult, "apiResultPayload must not be null");
        ApiResult<T> resultPayload = new ApiResult<>();
        resultPayload.setCode(apiResult.getCode());
        resultPayload.setMessage(apiResult.getMessage());
        resultPayload.setSuccess(apiResult.isSuccess());
        if (data != null) {
            resultPayload.setPayload(data);
        }

        return resultPayload;
    }

    /**
     * 转换异常为失败结果。
     *
     * @param runtimeException 异常
     * @return 失败结果
     */
    public static ApiResult<String> resolveException(BizException runtimeException) {
        return failOf(runtimeException.getCode(), runtimeException.getMessage(), null);
    }

    /**
     * 获取Result
     *
     * @return Result
     */
    public static ApiResult<String> toResult(Message message) {
        if (message.isSuccess()) {
            return ApiResult.successOf(message.getCode(), message.getText(), null);
        }

        return ApiResult.failOf(message.getCode(), message.getText(), null);
    }

    /**
     * 获取Result
     *
     * @return Result
     */
    public static <T> ApiResult<T> toResult(Message message, T data) {
        if (message.isSuccess()) {
            return ApiResult.successOf(message.getCode(), message.getText(), data);
        }
        return ApiResult.failOf(message.getCode(), message.getText(), data);
    }

    /**
     * 获取Result
     *
     * @return Result
     */
    public static ApiResult<String> toResult(Message message, String msg) {
        if (message.isSuccess()) {
            return ApiResult.successOf(message.getCode(), msg, null);
        }
        return ApiResult.failOf(message.getCode(), msg, null);
    }
}
